using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace GoodStuff.Web.Controls
{
	public delegate void PageIndexChangedEventHandler(object sender, PageIndexChangedEventArgs e);

	public class PageIndexChangedEventArgs : EventArgs
	{
		public PageIndexChangedEventArgs(int index)
		{
			PageIndex = index;
		}

		public int PageIndex;
	}

	/// <summary>
	/// Summary description for Pager.
	/// </summary>
	[System.ComponentModel.DefaultEvent("PageIndexChanged")]
	[System.ComponentModel.DefaultProperty("CurrentPageIndex")]
	public class Pager : WebControl, INamingContainer
	{
		private LinkButton Next;
		private LinkButton Previous;
//		private LinkButton First;
//		private LinkButton Last;
		private LinkButton[] SelectPage;
		
        private int _maxPages = 20;
		private int _pageSize = 10;

		public event PageIndexChangedEventHandler PageIndexChanged;

		private ICollection _dataSource;

		public ICollection DataSource
		{
			get 
			{
				return _dataSource;
			}
			set 
			{
				_dataSource = value;
			}
		}

		[Browsable(false)]
		public ICollection PagedData
		{
			get
			{
				PagedDataSource pager = new System.Web.UI.WebControls.PagedDataSource();
				pager.AllowPaging = true;
				pager.DataSource = _dataSource;
				pager.PageSize = this.PageSize;
				pager.CurrentPageIndex = this.CurrentPageIndex;

				return pager;
			}
		}

		public override void DataBind()
		{
			this.CreateChildControls();
			base.DataBind ();
		}

		/// <summary>
		/// The number of pages to show, e.g. 1 2 3 4 5
		/// </summary>
		[Browsable(false)]
		private int PagesToDisplay
		{
			get
			{
				return Math.Min(PageCount, MaximumPages);
			}
		}

		public int CurrentPageIndex
		{
			get 
			{ 
				//check range. If too large, go back to the last page.
				int index = Convert.ToInt32(ViewState["CurrentPageIndex"]);
				if(index > PageCount-1)
				{
					index = PageCount-1;
					ViewState["CurrentPageIndex"] = index;
				}
				if(index < 0)
				{
					index = 0;
					ViewState["CurrentPageIndex"] = index;
				}

				return index; 
			}
			set { ViewState["CurrentPageIndex"] = value; }
		}

		/// <summary>
		/// The maximum number of pages to display
		/// </summary>
		public int MaximumPages
		{
			get { return _maxPages; }
			set { _maxPages = value; }
		}

		[Browsable(false)]
		public int PageCount
		{
			get { 
				if(_dataSource == null)
				{
					return Convert.ToInt32(ViewState["PageCount"]);
				}

				// 0/5 >> 0 page (actually, no pages at all..)
				// 1/5 >> 1 page
				// 2/5 >> 1 page
				// 3/5 >> 1 page
				// 4/5 >> 1 page
				// 5/5 >> 1 page
				// 6/5 >> 2 pages
				// 7/5 >> 2 pages
				return (int)((_dataSource.Count + (PageSize-1)) / PageSize); }
		}

		public int PageSize
		{
			get { return _pageSize; }
			set { _pageSize = value; }
		}

		[Browsable(false)]
		public int FirstItemIndex
		{
			get { 
				return (this.CurrentPageIndex * this.PageSize) + 1;
			}
		}

		[Browsable(false)]
		public int LastItemIndex
		{
			get {
				return Math.Min(this._dataSource.Count, (this.CurrentPageIndex + 1)* this.PageSize);
			}
		}

		public string NextText
		{
			get
			{
				return Next.Text;
			}
			set
			{
				Next.Text = value;
			}
		}


		public string PrevText
		{
			get 
			{
				return Previous.Text;
			}
			set
			{
				Previous.Text = value;
			}
		}


		protected override void CreateChildControls()
		{
			this.Controls.Clear();

			Next = new LinkButton();
			Next.Text = "Volgende";			
			Next.CommandArgument = (this.CurrentPageIndex + 1).ToString();
			Next.Command += new CommandEventHandler(GotoPage);
			this.Controls.Add(Next);

			Previous = new LinkButton();
			Previous.Text = "Vorige";
			Previous.CommandArgument = (this.CurrentPageIndex - 1).ToString();
			Previous.Command += new CommandEventHandler(this.GotoPage);
			this.Controls.Add(Previous);

//			First = new LinkButton();
//			First.Text = "first page";
//			First.CommandArgument = 0;
//			First.Command += new EventHandler(this.GotoPage);
//			this.Controls.Add(First);
//
//			Last = new LinkButton();
//			Last.Text = "last page";
//			Last.CommandArgument = this.PageCount - 1;
//			Last.Command += new EventHandler(this.GotoPage);
//			this.Controls.Add(Last);

			//determine at what page number to start displaying.
			//(when PageCount > PagesToDisplay), e.g. 10 pages, currentpage = 4, maxdisplay = 6.
			//to make sure that at least 2 are visible around each, try to center the current page
			//in the list, if possible. This means that the first page to be displayed, is the
			//currentpage, minus half the amount of pages.

			int firstPageToDisplay = CurrentPageIndex - (PagesToDisplay/2);
			if(firstPageToDisplay <= 0)
			{	
				firstPageToDisplay = 0;
			}
			if(firstPageToDisplay > this.PageCount - PagesToDisplay)
			{
				firstPageToDisplay = this.PageCount - PagesToDisplay;
			}

			SelectPage = new LinkButton[this.PagesToDisplay];
			for(int i = 0; i < this.PagesToDisplay;i++)
			{
				SelectPage[i] = new LinkButton();
				SelectPage[i].Text = (i+firstPageToDisplay+1).ToString();
				SelectPage[i].CommandArgument = (i+firstPageToDisplay).ToString();
				SelectPage[i].Command += new CommandEventHandler(this.GotoPage);
				this.Controls.Add(SelectPage[i]);
			}
		}

		protected override object SaveViewState()
		{
			ViewState["PageCount"] = this.PageCount;
			return base.SaveViewState ();
		}


		private void GotoPage(object sender, CommandEventArgs e)
		{
			this.CurrentPageIndex = int.Parse((string)e.CommandArgument);

			if(this.PageIndexChanged != null)
			{
				this.PageIndexChanged(this, new PageIndexChangedEventArgs(this.CurrentPageIndex));
			}
			CreateChildControls();
		}

		protected override void Render(HtmlTextWriter writer)
		{
			if(this.PageCount > 1)
			{
				writer.Write("Pagina: ");
			}

			if(this.CurrentPageIndex > 0)
			{
				Previous.RenderControl(writer);
				writer.Write("&nbsp;|&nbsp;");
			}

			if(this.PageCount > 1)
			{
				foreach(LinkButton button in SelectPage)
				{
					if(this.CurrentPageIndex.ToString() == button.CommandArgument)
					{
						writer.Write("<B>" + (this.CurrentPageIndex + 1) + "</B>");
					}
					else
					{
						button.RenderControl(writer);
					}
					writer.Write("&nbsp;|&nbsp;");
				}
			}

			if(this.CurrentPageIndex < this.PageCount - 1)
			{
				Next.RenderControl(writer);
			}
		}
	}
}
